Оболочка программных труб C - PullRequest
0 голосов
/ 20 октября 2011

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

//Split the command and store each string in parameter[]
    cp = (strtok(command, hash));                      //Get the initial string (the command)
    parameter[0] = (char*) malloc(strlen(cp)+ 1);                     //Allocate some space to the first element in the array
    strncpy(parameter[0], cp, strlen(cp)+ 1);
    for(i = 1; i < MAX_ARG; i++)
    {
    cp = strtok(NULL, hash);                 //Check for each string in the array
    parameter[i] = (char*) malloc(strlen(cp)+ 1);
    strncpy(parameter[i], cp, strlen(cp)+ 1);                      //Store the result string in an indexed off array
        if(parameter[i]  == NULL)
        {
            break;
        }
    if(strcmp(parameter[i], "|") == 0)
    {
        cp = strtok(NULL, hash);
        parameter2[0] = (char*) malloc(strlen(cp)+ 1);
        strncpy(parameter2[0], cp, strlen(cp)+ 1);
        //Find the second set of commands and parameters
        for (j = 1; j < MAX_ARG; j++)
        {
            cp = strtok(NULL, hash);
            if (strlen(cp) == NULL)
            {
                break;
            }
            parameter2[j] = (char*) malloc(strlen(cp)+ 1);
            strncpy(parameter2[j], cp, strlen(cp)+ 1);
        }
        break;
    }

У меня проблемакогда я сравниваю cp и NULL, моя программа падает.Я хочу выйти из цикла после завершения записи для второго набора или параметров (что я и пытался сделать с помощью if (strlen (cp) == NULL)

Ответы [ 2 ]

1 голос
/ 20 октября 2011

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

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

Пример:

cat file1 file2 | sed s/frog/bat/

В приведенном выше примере cat вызывается только с двумя аргументами, file1 и file2. Кроме того, sed вызывается только с одним аргументом: s/frog/bat/.

0 голосов
/ 20 октября 2011

Давайте посмотрим на ваш код:

parameter[0] = malloc(255);

Поскольку strtok() разделяет исходный массив command, вам не нужно выделять дополнительное пространство с помощью malloc();Вы можете просто указать указатели parameter[n] на соответствующие разделы исходной командной строки.Однако, как только вы выйдете за пределы разделенных пробелами команд (в реальной оболочке символ | не обязательно должен быть окружен пробелами, а в вашей), вам, вероятно, потребуется скопировать части командной строкипримерно, так что это не совсем неправильно.

Вы должны проверить успешность выделения памяти.

cp = strtok(command, " ");                      //Get the initial string (the command)
strncpy(parameter[0], cp, 50);

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

for (i = 1; i < MAX_ARG; i++)

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

{
    parameter[i] = malloc(255);

Аналогичные комментарии о распределении памяти и проверке.

    cp = strtok(NULL, " ");
    parameter[i] = cp;

Упс!Там идет память.Извините за утечку.

    if (strcmp(parameter[i], "|") == 0)

Я думаю, что было бы лучше сделать это сравнение перед копированием ... Кроме того, вам не нужен канал в списке аргументов любой команды;это запись оболочки, а не часть списков аргументов команды.Вы также должны убедиться, что список аргументов первой команды завершается указателем NULL, тем более что i чуть ниже MAX_ARG, поэтому вы не будете знать, сколько аргументов было указано.

    {
        i = MAX_ARG;
        cp = strtok(NULL, " ");
        parameter2[0] = malloc(255);
        strncpy(parameter2[0], cp, 50);

Это кажется странным;Вы изолируете команду и затем обрабатываете ее аргументы отдельно.Установка i = MAX_ARG тоже кажется забавной, поскольку ваше следующее действие - разорвать петлю.

        break;
    }
    if(parameter[i]  == NULL)
    {
        break;
    }
}

//Find the second set of commands and parameter
//strncpy(parameter2[0], cp, 50);
for (j = 1; j < MAX_ARG; j++)
{
    parameter2[j] = malloc(255);
    cp = strtok(NULL, " ");
    parameter2[j] = cp;
}

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

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

При написании кода для Bash или эквивалентной оболочки я часто использую нотации, такие как этот скрипт, который я использовал сегодня несколько раз.

ct find /vobs/somevob \
    -branch 'brtype(dev.branch)' \
    -version 'created_since(2011-10-11T00:00-00:00)' \
    -print |
grep -v '/0$' |
xargs ct des -fmt '%u %d %Vn %En\n' |
grep '^jleffler ' |
sort -k 4 |
awk '{ printf "%-8s %s %-25s %s\n", $1, $2, $3, $4; }'

Не имеет большого значения, что он делает (но он находит все проверки, которые я сделал с 11 октября в определенной ветке в ClearCase);важно, что я использовал обозначение.(Да, возможно, его можно было бы оптимизировать - это не стоило того.) Точно так же, это не обязательно то, с чем вам нужно сейчас иметь дело - но оно дает вам представление о том, куда вам нужно идти.

...