Использование execvp с dup2 вызывает ошибку EFAULT - PullRequest
0 голосов
/ 01 февраля 2019

Я собираю небольшую оболочку linux и пытаюсь реализовать оператор >, чтобы перенаправить вывод команд в файл.

У меня проблема в том, что когда я пытаюсь что-то запуститькак ls > test.txt, я получаю Bad Address (EFAULT) ошибку.

Однако, если я пытаюсь сделать это без перенаправления, все работает как положено.

Я обрезал код доминимум, чтобы проверить только для ls, но я все еще получаю ту же ошибку, вот код.

int saved_stdout;
__pid_t id = fork();

if (id == 0) {
    saved_stdout = dup(1);

    int fd = open("test.txt", O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);

    dup2(fd, STDOUT_FILENO);
    dup2(fd, STDERR_FILENO);

    close(fd);

    char* args[] = {"\0"};

    execvp("ls", args);

    fprintf(stderr, "Value of errno: %d\n", errno);
    perror("Error printed by perror");

} else {
    int status;
    waitpid(id, &status, 0);

    if (saved_stdout) {
        dup2(saved_stdout, 1);
        close(saved_stdout);
    }
}

Кто-нибудь как идея о том, что я здесь делаю неправильно?

Большое спасибо

Ответы [ 2 ]

0 голосов
/ 01 февраля 2019

Есть ли у кого-нибудь идеи о том, что я здесь делаю неправильно?

Основная проблема, вероятно, состоит в том, что ваши аргументы execvp() неверны:

    char* args[] = {"\0"};

    execvp("ls", args);

Есть две вещи, которые определенно не так с этим:

  1. Массив аргументов должен заканчиваться нулевым указателем."\0" является , а не нулевым указателем;скорее это массив, содержащий два нулевых символа , и он распадается на действительный, поэтому ненулевой, указатель.

  2. Даже если "\0" были нулемуказатель, у тебя будет один короткий аргумент.Первый элемент вектора аргумента с индексом 0 должен быть указателем на строку, представляющую имя программы.

Другими словами:

 char* args[] = { "ls", NULL };

 execvp("ls", args);

Дополнительновыполняемое вами перенаправление не согласуется с обработкой в ​​оболочке POSIX оператора перенаправления >.В такой форме этот оператор перенаправляет только стандартный вывод, а не стандартную ошибку.Кроме того, он должен открывать указанный файл только для записи, а не для чтения / записи, потому что запись в него - это все, что нужно программе.Открытие его для чтения / записи может привести к невозможности перенаправления в существующий файл, для которого у пользователя есть разрешения на запись, но нет прав на чтение.

Кроме того, режим файла, который вы указываете для события, когда создается новый файлтакже производит поведение, несовместимое с оболочкой POSIX.Вы должны указать разрешения на чтение / запись для пользователя, группы и других пользователей и разрешить их изменение в соответствии с действующим umask:

int fd = open("test.txt", O_WRONLY | O_CREAT,
    S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
0 голосов
/ 01 февраля 2019

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

Также следует помнить, что массив аргументов включает в себя argv[0].

Таким образом, массив должен выглядеть как

char* args[] = { "ls", NULL };
...