получение команды оболочки из пользовательского ввода и выполнение программы на C - PullRequest
0 голосов
/ 06 мая 2011

в настоящее время работает над программой, которая получает команду ввода для оболочки Linux и выполняет ее, создавая дочерний процесс.

#include <sys/types.h>
#include <sys/wait.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>

int main(int argc, char * argv[])
{ 
  int pid, status;
  if (argc < 2) {
    printf("Usage: %s command, [arg1 [arg2]...]\n", argv[0]);
    return EXIT_FAILURE;
  }
  printf("Starting %s...\n", argv[1]);
  pid = fork();
  if (pid == 0) {
    execvp(argv[1], &argv[1]);
    perror("execvp");
    return EXIT_FAILURE; // Never get there normally
  } else {
    if (wait(&status) == -1) {
      perror("wait");
      return EXIT_FAILURE;
    }
  }
  return EXIT_SUCCESS;
}

Работает с вводом типа ./program command arg, но необходим для получения различных команд с аргументами, например: ./program command arg command arg .....

Есть предложения?

Ответы [ 4 ]

0 голосов
/ 06 декабря 2011

Я думаю, что вопрос здесь в разборе argv.

Вот фиктивный логический поток:

    for(i = 1; i < argc; i++)
    {
        isCommand = CheckCmd(argv[i]);  /* check if argv[i] is a command */
        if (isCommand)
        {
            for(; i < argc; i++)
            {
                isCommand = CheckCmd(argv[i]);  /* check if argv[i] is a command */
                if (isNotCommand)
                {
                    PushOption(argv[i]); /* save options */
                } else
                {
                    /* Get Command and options from stack */
                    /* execute command with fork/execv */
                }
            }
        } 
    }

Единственное, что вам здесь нужно, - реализовать CheckCmd и PushOption / PopOption.1006 *

0 голосов
/ 06 мая 2011

argc говорит вам размер argv

Вам нужно извлечь их из argv, используя эту информацию.

Обратите внимание, что это не решает проблему команд с различным количеством аргументов.

Изменить по этой причине в ответ на комментарии:

Вы можете посмотреть на getopt(), который позволит вам сделать это:

 ./program -c "command arg1 arg2" -c "command arg1" ...

Проблема в том, что вам нужно различать наборы команд / аргументов. getopt() по крайней мере приведет вас на полпути, тогда вам просто нужно разобрать каждый набор. Хотя это действительно излишне, поскольку это ваш единственный тип ввода. Итерация по argv будет в этом случае такой же простой.

Другой вариант - разделить их разделителем:

./program command arg1, command arg1 arg2, ... 

Вам нужно будет перебрать argv и найти запятую, чтобы узнать, что набор команд / аргументов завершен. Или объедините все аргументы argv в строку и используйте strtok(). Вроде некрасиво ИМХО но выполнимо.

0 голосов
/ 06 мая 2011

Оболочка - это сложная часть программного обеспечения, недавно мне пришлось реализовать ее для класса операционных систем, и это было сложно; и нам нужно было контролировать только одну команду для каждого входа (хотя мы также должны были реализовать перенаправление ввода-вывода и конвейерную передачу, и нам пришлось выполнять поиск пути вручную, а затем выполнить с помощью execv()).

Проблема, с которой вы столкнетесь, заключается в том, что на самом деле нет никакого способа определить, является ли следующая строка аргумента в массиве параметров командной строки командой или аргументом предыдущей команды. Единственный способ различать команды и их аргументы - это, если вы знаете , что он будет чередоваться command arg command arg ..., или у вас есть какое-то другое стандартизированное число аргументов в команде (что не очень полезно), или если у вас есть разделитель между командами, как точка с запятой: command arg; command arg arg arg; ...

В случае, если вы знаете , он будет чередоваться, тогда вы можете просто перебрать аргументы следующим образом:

for(int i = 1; i < argc; i += 2)
{
   //command is argv[i], arg is argv[i + 1]
}

Лучший способ сделать это - вместо использования параметров командной строки создать приглашение ввода, а затем обработать одну команду на строку, как при обычном использовании оболочки.

0 голосов
/ 06 мая 2011

Вы на самом деле не говорите, в чем заключается ваша проблема, но я полагаю, что у вас возникают проблемы при определении того, как каждый разветвленный процесс будет использовать параметры.

Я думаю, что вы делаете, что каждый раз, когда вы форкаете, вам нужно продвигать указатель argv на следующую пару команда / аргумент. Этот цикл разветвления завершается, когда команда является нулевым ограничителем.

Надеюсь, я понял ваш вопрос, потому что вы на самом деле не указали, в каком аспекте этой проблемы вы застряли.

...