我有一个类似于基本bash shell的程序。我可以从shell运行/bin
目录中的程序。我有一个内置命令checkEnv,它使用寻呼机显示与printenv | sort | less
完全相同的系统变量,但是当less
完成后,程序退出。我想编程返回shell。你能告诉我怎么做吗?我创建管道的方式是
cmd[0].argv= printenv;
cmd[1].argv= sort;
cmd[2].argv= pager_cmd;
fork_pipes(3, cmd);
声明cmd
:
struct command
{
char * const *argv;
};
struct command cmd[3];
我有辅助功能来分叉:
/* 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;
}
我的问题是程序在使用内置命令checkEnv
时退出。我希望程序返回到主循环,即我的shell的命令提示符:
while(1) {
printf("miniShell>> ");
memset(line, 0, sizeof line); /*Reset*/
if(!fgets(line, BUFFER_LEN, stdin)) {
break;
}
你能帮助我吗?
答案 0 :(得分:1)
如果使用exec(或任何exec函数类型),exec下定义的每一行都不会被执行,因为exec就像在这个程序中执行另一个程序一样。
答案 1 :(得分:1)
我的猜测是你忘了给第三个进程打电话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
}
}