简体   繁体   中英

C Infinite loop in shell after piping commands into it

I am currently trying to build a custom shell for a class. I'm able to execute commands issued from this shell without problem, but if I pipe my command into my shell, I end up with an infinite-loop. I am out of ideas why this might happen. The example below would cause an infinite loop.

echo "ls" | ./myshell

Of course I have to redirect the output of programs, if a pipe within a command would occur, eg ls | grep test ls | grep test . Within my shell, this works flawlessly. I am using fork() , execv() and of course pipe + dup for redirecting streams between child processes.

It seems, as if fgets() would not clear the STDIN_FILENO from the last issued command.

For the command echo "ls" | ./myshell echo "ls" | ./myshell my program would do the following: (minimal working example)

EDIT: Minimal working example

#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>

int running = 1;
int exit_code = 0;

char cwd[256];
char command[256];
char args[10][256];
char buffer[256] __attribute__((aligned(4096)));

void handle_command(char* buffer, int buffer_size)
{
  int c = 0;
  int argsCount = -1;
  int lastIndex = 0;

  for (c = 0; c < buffer_size && buffer[c]; c++)
  {
    if (argsCount > 10)
    {
      argsCount = 10;
      printf("Argument Count is limited to 10 (no dynamic memory allocation) all other arguments will be ignored\n");
      break;
    }
    if (buffer[c] == '\r' || buffer[c] == '\n' || buffer[c] == ' ')
    {
      if (argsCount == -1)
      {
        memcpy(command, buffer + lastIndex, c - lastIndex);
        command[c - lastIndex] = 0;
      }
      else
      {
        memcpy(args[argsCount], buffer + lastIndex, c - lastIndex);
        args[argsCount][c - lastIndex] = 0;
      }
      argsCount++;
      lastIndex = c + 1;

    }
  }

  if (strcmp(command, "exit") == 0)
  {
    c = 4;
    while (buffer[c] == ' ')
      c++;
    exit_code = atoi(&buffer[c]);
    printf("Exiting Shell with exit_code %d\n", exit_code);
    running = 0;
  }
  else if (strcmp(command, "") != 0)
  {
    // -------------- Add structure to commands --------------------------------
    struct command_struct{
      char *options[10];
    } sub_commands[1];
    // Simplified code, there would be a dynamic amount of sub_commands
    // and further logic to handle pipes and < > >>

    // initialize first command, would work dynamically
    sub_commands[0].options[0] = command;
    sub_commands[0].options[1] = NULL;

    int status;
    int pid = fork();
    if (pid == 0) {
      execvp(sub_commands[0].options[0], sub_commands[0].options);
      perror("Error: Reached code after execvp\n");
    } else if (pid < 0) {
      perror("Cannot fork!\n");
    }
    wait(&status);
  }
}


int main(int argc, char *argv[])
{
  cwd[0] = '/';

  do
  {
    printf("\n%s %s%s", "SHELL:", cwd, "> ");
    fgets(buffer, 255, stdin);
    buffer[255] = 0;
    handle_command(buffer, 256);
    for (size_t a = 0; a < 256; a++)
      buffer[a] = 0;

  } while (running);

  return exit_code;
}

EDIT I have to point out, that parts of this code were given in this class.

Any help whatsoever would be greatly appreciated!

OP code will only quit the main() do loop when running == 0 .

running = 0; only occurs when strcmp(command, "exit") == 0 and it is not clear that with string parsing that just "exit" is ever loaded in command . Note: command is not cleanly initialized per each handle_command() call and command does not need to be a global variable.

Adjust code to quit when fgets() returns NULL and review line processing. Suggest:

do {
  printf("\n%s %s%s", "SHELL:", cwd, "> ");
  if (fgets(buffer, sizeof buffer, stdin) == NULL) {
    break; 
  }
  // lop off potential end-of-line character(s)
  buffer[strcspn(buffer,"\r\n")] = '\0';
  handle_command(buffer, sizeof buffer);
} while (running);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM