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

时间:2016-01-16 16:01:04

标签: c linux shell fork

我正在建立一个像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);
    } 
}
}

1 个答案:

答案 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会终止您的父进程。 我根本没有看到为什么你需要这里的模板,我想你可以完全放弃它。