Я реализовал простую оболочку типа bash, используя программу c, но она не работает должным образом - PullRequest
0 голосов
/ 08 января 2019

Я создал одну программу, похожую на bash, но когда я попытался выполнить, она работает нормально только в первый раз, а затем после того, как она не работает должным образом

Последний выполненный вывод постоянно отображается вместо запроса нового ввода

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

 char full_cmd[20];

 void command_source(char *cmd)
 {

    FILE *fp;
    char output[20];
    char *token;
    token = strtok(cmd," ");
    strcpy(full_cmd,"which ");
    strcat(full_cmd,token);
    fp = popen(full_cmd,"r");
    while (fgets(output, 20, fp) != NULL) {
            strcpy(full_cmd,output);
    }
    full_cmd[strlen(full_cmd)-1] = '\0';

    token = strtok(NULL," ");
    while (token != NULL)
    {
            strcat(full_cmd,token);
            token = strtok(NULL," ");
    }

  }

  void get_input(char input[10])
  { 
    printf("Enter the command:");
    scanf("%[^\n]s",input);
  }

  int launch_shell(char *buff[50],int status)
  {
    pid_t pid = fork();
    if( pid == 0 )
    {
            execv(buff[0],buff);
    }
    else if (pid > 0)
    {
            pid_t wpid = waitpid(pid, &status, 0);
    }
    else
            return 0;
    return 1;
  }

  int main()
  {
    char *buff[50];
    int status;
    char input[10];
    int count=0,ret=1;
    while(ret == 1)
    {
            get_input(input);
            command_source(input);
            strcpy(buff[0],full_cmd);
            buff[1] = NULL;
            int ret = launch_shell(buff,status);
    }
  }

Ожидаемый:

Enter the command:ls 
server.c server
Enter the command:ls -l
server.c
server

Фактические результаты:

Enter the command:ls
server  server.c
server  server.c
server  server.c
server  server.c
server  server.c
server  server.c
server  server.c
server  server.c
server  server.c
server  server.c
server  server.c
server  server.c
server  server.c
server  server.c
...

Пожалуйста, помогите мне, ребята, выяснить проблему в этом. Я трачу весь день на это. Но я не мог.

1 Ответ

0 голосов
/ 08 января 2019

с заявлением

scanf("%[^\n]s",input);

вы говорите "читайте, пока не появится новая строка". Таким образом, после первого ввода символ новой строки остается во входном потоке, что предотвращает немедленное прекращение последующего чтения ввода. Лучше было бы использовать fgets() вместо scanf().

Вы можете передать аргумент размера функции get_input, такой как:

  void get_input(char input[10], size_t size)
  { 
    printf("Enter the command:");
    if (fgets(input, size, stdin) != NULL) {
        char *p = strchr(input, '\n');
        if (p) *p = '\0';
    } else {
        fprintf(stderr, "fgets failed\n");
        exit(1);
    }
  }

и назовите его:

    get_input(input, sizeof input);

У вас также есть ряд проблем:

1

strcpy(buff[0],full_cmd);

не соответствует, потому что buff[0] не инициализирован. Вместо этого вы можете просто назначить:

buff[0] = full_cmd;
  1. У вас не может быть аргументов для команды в вашем текущем подходе. Потому что каждый аргументов и команды необходимо передавать как разные параметры массива от buff до execv.

    Таким образом, вам нужно разделить входные данные на основе пробелов и поместить их в массив buff перед вызовом launch_shell. Например, «ls -l» будет единственным аргументом для execv (передается через buff[0]). Но это не то, что execv принимает. Вам нужно поместить "ls" в buff[0] и "-l" в buff[1] и NULL в buff[2], а затем вызвать execv.

...