линукс исполняемый файл ; ls не может получить доступ |, Нет такого файла или каталога

Я пытаюсь закодировать оболочку. Но моя оболочка не выполняет команду -ls -l | меньше. Я использую execvp. код приведен ниже.

#include <stdio.h>
#include <unistd.h>
#include <string.h>

int main(){
    int pid, status, num, len;
    char str[1000], cwd[100];
    char* word[100];

    getcwd(cwd, sizeof(cwd));

    while(1){
        chdir(cwd);

        printf("%s > ", cwd);

        gets(str);

        pid=vfork();

        if(pid == 0){
            num = 0;
            word[num] = strtok (str, " ");

            while (word[num] != NULL) {
                word[num] = strdup (word[num]);
                len = strlen (word[num]);
                if (strlen (word[num]) > 0)
                    if (word[num][len-1] == '\n')
                        word[num][len-1] = '\0';
                word[++num] = strtok (NULL, " ");
            }

            if(strcmp(word[0], "cd") == 0){
                chdir(word[1]);
                getcwd(cwd, sizeof(cwd));
            }
            else{
                execvp(word[0],word);
            }

            exit(0);
        }
        else{
            wait(&status);
        }
    }

    return 0;
}

person odbhut.shei.chhele    schedule 03.09.2013    source источник
comment
Насколько я знаю, | — это токен, связанный с оболочкой. Выполнение этого вне оболочки на самом деле не работает, потому что это оболочка, которая читает | и делает волшебство. Без оболочки, чтобы сделать волшебную трубку... это не работает.   -  person Cornstalks    schedule 04.09.2013
comment
ТАК есть ли другой способ запустить |? можно как-то строку и перебором заставить работать   -  person odbhut.shei.chhele    schedule 04.09.2013
comment
@Cornstalks говорит правду. execvp написан для выполнения одной команды с набором параметров (если нужно). Вы можете попробовать system вызвать полноценную командную строку оболочки.   -  person lurker    schedule 04.09.2013
comment
Прежде чем использовать vfork(), прочитайте, что вам разрешено делать в дочернем процессе. Я не думаю, что chdir() или getpwd() разрешены. Вместо этого используйте fork(). Вероятно, это не главная ваша проблема (пока), но будьте очень, очень осторожны с ограничениями на vfork().   -  person Jonathan Leffler    schedule 04.09.2013
comment
Среди многих возможностей см. Программа на C с каналами для выполнения ps aux | grep firefox | tee processes.txt.   -  person Jonathan Leffler    schedule 04.09.2013
comment
Кроме того, я просто хочу сказать, что хотел бы сказать, что это вместо его, но, увы, больше не могу редактировать свой комментарий. На всякий случай, если у кого-то глаза кровоточат от опечатки.   -  person Cornstalks    schedule 04.09.2013
comment
Изучите исходный код существующих бесплатных программных оболочек, таких как sash или bash, и прочтите Продвинутое программирование в Linux.   -  person Basile Starynkevitch    schedule 04.09.2013


Ответы (1)


ls -l | less на самом деле является командной строкой оболочки, состоящей из двух процессов, соединенных конвейером. Вызов execvp() может породить только один процесс.

Если вы хотите сделать это из своей программы, вы должны явно вызвать оболочку - либо с помощью вызова system(), либо путем изменения командной строки на sh -c 'ls -l | less'. Ваш массив word должен выглядеть так:

word[0] = "sh"
word[1] = "-c"
word[2] = "ls -l | less"
word[3] = NULL

[EDIT] В качестве альтернативы вы можете сделать то, что оболочка делает внутри: создать два процесса и соединить их с помощью канала. Это потребует использования вызовов fork(), pipe(), dup2() и execve(). Однако вызов оболочки требует гораздо меньше работы, а поскольку less в любом случае является интерактивной программой, вам не нужно особо беспокоиться о производительности: все, что занимает менее 100 мс, воспринимается как мгновенное.

person Krzysztof Kosiński    schedule 03.09.2013
comment
+1 Просто за злоупотребление sh командой execvp. Не ожидал этого =P. - person WhozCraig; 04.09.2013
comment
@WhozCraig: GNU libc system() внутри делает то же самое. См.: исходное программное обеспечение. .org/git/?p=glibc.git;a=blob;f=sysdeps/posix/ - person Krzysztof Kosiński; 04.09.2013
comment
@KrzysztofKosiński Это потрясающе. Не имел представления. Спасибо! - person WhozCraig; 04.09.2013
comment
popen() тоже может быть полезно. - person konsolebox; 04.09.2013
comment
Кодирование оболочки с использованием системной оболочки (через system, popen или выполнение /bin/sh) не совсем соответствует целям домашнего задания..... - person Basile Starynkevitch; 04.09.2013