繁体   English   中英

C将命令传递到外壳后,外壳中的无限循环

[英]C Infinite loop in shell after piping commands into it

我目前正在尝试为一个类构建自定义外壳。 我能够执行从该外壳发出的命令而不会出现问题,但是如果将命令通过管道传递到外壳中,则会导致无限循环。 我不知道为什么会发生这种情况。 下面的示例将导致无限循环。

echo "ls" | ./myshell

当然,如果命令中出现管道,例如ls | grep test ,我必须重定向程序的输出。 ls | grep test 在我的壳中,这完美无瑕。 我正在使用fork()execv()以及pipe + dup来在子进程之间重定向流。

似乎fgets()不会从最后发出的命令中清除STDIN_FILENO

对于命令echo "ls" | ./myshell echo "ls" | ./myshell我的程序将执行以下操作:(最小的工作示例)

编辑:最小的工作示例

#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;
}

编辑我必须指出,此类代码的某些部分在此类中给出。

任何帮助将不胜感激!

仅在running == 0时,OP代码才会退出main() do循环。

running = 0; 仅在strcmp(command, "exit") == 0时发生strcmp(command, "exit") == 0并且不清楚通过字符串分析是否command加载了"exit" 注意:每个handle_command()调用均未对command进行干净初始化,并且command不必是全局变量。

调整代码以在fgets()返回NULL时退出并查看行处理。 建议:

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);

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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