如何在调用exec后让程序返回原始循环?

时间:2021-01-23 20:50:04

I have a program that is similar to a basic bash shell. I can run programs in the /bin directory from the shell. I have a builtin command checkEnv that uses a pager to display system variables exactly like printenv | sort | less but when less has completed, the program exits. I want to program to return to the shell. Can you tell my how I can do it? The way I create the pipeline is

我有一个类似于基本bash shell的程序。我可以从shell运行/ bin目录中的程序。我有一个内置命令checkEnv,它使用寻呼机来显示与printenv |完全相同的系统变量排序|较少但是当完成较少时,程序退出。我想编程返回shell。你能告诉我怎么做吗?我创建管道的方式是

cmd[0].argv= printenv;
cmd[1].argv= sort;
cmd[2].argv= pager_cmd;
fork_pipes(3, cmd);

where cmd is declared:

声明cmd的位置:

struct command
{
    char * const *argv;
};
struct command cmd[3];

I have helper functions to fork:

我有辅助函数来fork:

/* Helper function that forks pipes */
static void fork_pipes(int n, struct command *cmd)
{
    int i;
    int in = 0;
    int fd[2];
    int take_return;
    for (i = 0; i < n - 1; ++i)
    {
        take_return = pipe(fd);
        ++take_return; /* Please the -O4 switch to gcc */
        spawn_proc(in, fd[1], cmd + i);
        close(fd[1]);
        in = fd[0];
    }
    if (dup2(in, 0) < 0)    {
        err_syserr("dup2() failed on stdin for %s: ", cmd[i].argv[0]);
    }
    fprintf(stderr, "%d: executing %s\n", (int)getpid(), cmd[i].argv[0]);
    execvp(cmd[i].argv[0], cmd[i].argv);
    err_syserr("failed to execute %s: ", cmd[i].argv[0]);
}

/* Helper function that spawns processes */
static int spawn_proc(int in, int out, struct command *cmd)
{
    pid_t pid;
    if ((pid = fork()) == 0)
    {
        if (in != 0)
        {
            if (dup2(in, 0) < 0)
                err_syserr("dup2() failed on stdin for %s: ", cmd->argv[0]);
            close(in);
        }
        if (out != 1)
        {
            if (dup2(out, 1) < 0)
                err_syserr("dup2() failed on stdout for %s: ", cmd->argv[0]);
            close(out);
        }
        fprintf(stderr, "%d: executing %s\n", (int)getpid(), cmd->argv[0]);
        execvp(cmd->argv[0], cmd->argv);
        err_syserr("failed to execute %s: ", cmd->argv[0]);
    }
    else if (pid < 0)   {
        err_syserr("fork failed: ");
    }
    return pid;
}

My problem is that the program exits when using the builtin command checkEnv. I want the program to return to the main loop that is the command prompt for my shell:

我的问题是程序在使用内置命令checkEnv时退出。我希望程序返回主循环,这是我的shell的命令提示符:

 while(1) {

        printf("miniShell>> ");
        memset(line, 0, sizeof line); /*Reset*/
        if(!fgets(line, BUFFER_LEN, stdin)) {
            break;
        }

Can you help me?

你可以帮我吗?

2 个解决方案

#1


1  

My guess is that you forgot to call fork for the third process. You use just exec for it which means your main process (the miniShell) is substituted by pager_cmd. You should write something like that:

我的猜测是你忘了为第三个进程调用fork。你只使用exec,这意味着你的主进程(miniShell)被pager_cmd取代。你应该这样写:

static void fork_pipes(int n, struct command *cmd)
{
    ... //calling spawn_proc two times
    pid = fork();
    if(pid == 0) { //child process (pager_cmd)
        execvp(cmd[i].argv[0], cmd[i].argv);
        err_syserr("failed to execute %s: ", cmd[i].argv[0]);
    } else if(pid > 0) {
        //call wait() for three pids we obtained by forking
    } else {
        //error handling
    }
}

#2


1  

If you use exec (or any exec function type) every line defined under exec will not be executed because exec is like executing another program inside this program.

如果使用exec(或任何exec函数类型),exec下定义的每一行都不会被执行,因为exec就像执行该程序中的另一个程序一样。

#1


1  

My guess is that you forgot to call fork for the third process. You use just exec for it which means your main process (the miniShell) is substituted by pager_cmd. You should write something like that:

我的猜测是你忘了为第三个进程调用fork。你只使用exec,这意味着你的主进程(miniShell)被pager_cmd取代。你应该这样写:

static void fork_pipes(int n, struct command *cmd)
{
    ... //calling spawn_proc two times
    pid = fork();
    if(pid == 0) { //child process (pager_cmd)
        execvp(cmd[i].argv[0], cmd[i].argv);
        err_syserr("failed to execute %s: ", cmd[i].argv[0]);
    } else if(pid > 0) {
        //call wait() for three pids we obtained by forking
    } else {
        //error handling
    }
}

#2


1  

If you use exec (or any exec function type) every line defined under exec will not be executed because exec is like executing another program inside this program.

如果使用exec(或任何exec函数类型),exec下定义的每一行都不会被执行,因为exec就像执行该程序中的另一个程序一样。