linux execvp; 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

[РЕДАКТИРАНЕ] Като алтернатива можете да направите това, което черупката прави вътрешно: да създадете два процеса и да ги свържете с канал. Това ще включва използването на fork(), pipe(), dup2() и execve() повиквания. Извикването на обвивката обаче е много по-малко работа и тъй като less така или иначе е интерактивна програма, не е нужно да се тревожите толкова много за производителността: всичко, което отнема по-малко от 100 ms, се възприема като мигновено.

person Krzysztof Kosiński    schedule 03.09.2013
comment
+1 Само за злоупотребата с sh като команда execvp. Не очаквах това =P. - person WhozCraig; 04.09.2013
comment
@WhozCraig: GNU libc system() вътрешно прави точно същото нещо под капака. Вижте: sourceware .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