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
cmd[0].argv= printenv;
cmd[1].argv= sort;
cmd[2].argv= pager_cmd;
fork_pipes(3, cmd);
where cmd
is declared:
struct command
{
char * const *argv;
};
struct command cmd[3];
I have helper functions to 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:
while(1) {
printf("miniShell>> ");
memset(line, 0, sizeof line); /*Reset*/
if(!fgets(line, BUFFER_LEN, stdin)) {
break;
}
Can you help me?
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:
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
}
}
Collected from the Internet
Please contact [email protected] to delete if infringement.
Comments