execvp - ls: fts_open: нет такого файла или каталога

В настоящее время я борюсь с этой ошибкой. Я пишу эмулятор оболочки, используя fork() для выполнения команды с помощью execvp();. Почти каждая команда, которую я пытаюсь проанализировать в своей оболочке, работает отлично, за исключением ls без аргументов. Если я попытаюсь выполнить ls -lah, все работает, но простой ls не будет, получая следующую ошибку:

ls: fts_open: No such file or directory

Вот фрагмент моего кода: (только самое необходимое)

pid = fork();
      if (pid==0)
      {
        puts("CHILD");
        puts(args[0]);
        puts(args[1]);
        printf("%d\n", strlen(args[1]));
        args[2] = NULL;
        execvp(args[0], args);
      }
      else wait(NULL);
      puts("BACK TO PARENT");
    }

и вот вывод для ls:

ls
CHILD
ls

0
ls: fts_open: No such file or directory
BACK TO PARENT

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

Любая идея о том, что это может быть?

РЕДАКТИРОВАТЬ:

Престижность Джонатану Леффлеру за то, что он это обнаружил: (также кажется, что это просто проблема на Mac)

Дело в том, что args[1] на самом деле не пуст, поэтому ОС пытается открыть файл '', которого, очевидно, не существует, и, судя по всему, создать его нельзя, так как он не действительно имя.

Итак, вот что я сделал: проверил длину args[1]. Если это 0, установите его в NULL. (просто освобождение памяти не очень помогло)

pid = fork();
      if (pid==0)
      {
        puts("CHILD");
        puts(args[0]);
        puts(args[1]);
        if (strlen(args[1]) == 0)
            args[1] = 0;
        args[2] = NULL;
        execvp(args[0], args);
      }
      else wait(NULL);
      puts("BACK TO PARENT");
    }

person Arthur Camara    schedule 09.04.2013    source источник
comment
Можете ли вы показать полное определение args (что установлено в args[1], что пусто?), а также больше вашего кода?   -  person Jorge Israel Peña    schedule 09.04.2013


Ответы (1)


Если аргументов больше нет, указатель должен быть нулевым, а не ненулевым указателем на строку нулевой длины.

pid = fork();
if (pid==0)
{
    puts("CHILD");
    puts(args[0]);
    fflush(stdout);
    args[1] = 0;
    execvp(args[0], args);
    fprintf(stderr, "Failed to exec %s\n", args[0]);
    exit(1);
}
else
    wait(NULL);
puts("BACK TO PARENT");

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

$ ls ''
ls: fts_open: No such file or directory
$

Вы тоже работаете на Mac? (Сказать, что я был удивлен, увидев то же самое сообщение, не значит описать мою реакцию!) Что еще более интригует, так это то, что создание файла fts_open, похоже, не избавляет от сообщения об ошибке. Странное поведение ls, но в ответ на недопустимый запрос (нет имен файлов, которые являются пустой строкой).

person Jonathan Leffler    schedule 09.04.2013
comment
Спасибо! Я обновлю свой вопрос, чтобы показать, каким стал мой код, но, в основном, я проверил len args[1] и, если он равен 0, просто сделал его NULL. - person Arthur Camara; 09.04.2013
comment
Да, я тоже работаю на Mac. Я сделал пару быстрых исследований, и кажется, что fts_open что-то связанное с ОС. Возможно по поводу открытия файлов. - person Arthur Camara; 09.04.2013
comment
fts_open — это внутренняя функция для обхода иерархии каталогов. Сообщение об ошибке означает, что произошла ошибка в программе ls, в функции fts_open, которая вернула код ошибки ENOENT. - person melpomene; 11.10.2015