用execl中的变量替换字符串值并停止执行

Replace string value with variable in execl and execution stopping

我正在构建一个类似于 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;
}

这就是我的子进程被新进程替换的方式,一个名为 "hello" 的程序。它只是将 "Hello World" 打印到屏幕上。

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);
    } 
}

}

它工作得很好。但是我想用一个变量替换那个 "hello" ,就像我键入“./hello”从那里获取 "hello" 部分并将其用作 execl() 函数中的变量一样。

我试过这样做,但似乎无法找到 "hello"。我尝试将其打印在屏幕上,它按应有的方式打印 "hello" 。任何想法为什么不执行该过程?

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);
    } 
}

}

第二个问题:在我的第一个执行方法中,它在 execl() 函数中使用 "hello" 作为字符串执行得很好。我总是在屏幕上打印“$ >”字符串,它要求输入。但是当子进程完成他的执行时,整个程序就停止了。如果我愿意,我怎样才能让他再次在屏幕上打印那个“$>”字符串,以便我执行其他命令。提前致谢

更新:执行外部命令的函数

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] = '[=13=]';

    //Replace child process with a new process
    if(execl(program, program, NULL) == -1){
        fprintf(stderr, "Error executing new process!\n");
        exit(3);
    } 
}
}

fgets 在字符串中包含尾随的换行符。您必须剥离它才能正确调用二进制文件。此外,您的 memcpy 不会将必要的零字节复制为字符串终止符。尝试:

program[len-1] = '[=10=]';

memcpy() 之后。 这应该有所帮助。

另请注意:此代码容易出现缓冲区溢出,因为程序固定为 10 个字节,而 cmd 可以更长。 你可以这样做:

int len = strlen(cmd) - 2;
char program[len];
memcpy(program, &cmd[2],len);
program[len-1] = '[=11=]';

以防止这种情况发生。如果你不关心修改cmd,你也可以这样做:

cmd[strlen(cmd)-1] = '[=12=]';

if (execl(cmd+2, cmd+2, NULL) ...

还有一件事:

甚至不需要删除 ./ 部分,execl 可以正常工作。

在父进程中:

if(pid){
    //Parent process
    dup2(commpipe[1],1);

您将进程的标准输出设置为 commppipe。因此,所有后续的 printf 都将尝试写入损坏的管道,因此 SIGPIPE 会终止您的父进程。 我完全不明白为什么你需要这里的 commpipe,我认为你可以完全忽略它。