Почему мой выдающийся файловый дескриптор GNAT не работает?

В рамках небольшого проекта я пишу оболочку на Аде. Таким образом, когда я исследовал системные вызовы, я узнал, что есть три способа сделать это.

  1. Системные вызовы POSIX, которые, вероятно, наименее надежны.
  2. Передача аргументов в system() C, чего я на самом деле не хотел делать, так как речь шла о написании эмулятора на Аде, а не на C.
  3. Использование библиотек времени выполнения GNAT.

Я выбрал последний вариант, считая его наиболее «похожим на Аду». Я нашел фрагмент кода на RosettaCode здесь. Я скопировал и вставил его и скомпилировал после изменения «cmd.exe» на «ls» и удаления определения второго аргумента. Однако ничего не происходит, когда я запускаю исполняемый файл. Оболочка просто возвращается к подсказке. Я проверил это на двух разных компьютерах, на одном была установлена ​​Fedora 21, а на другом — Debian Jessie. Вот что я сделал, чтобы проверить это:

  • Видно, если это вызвано отсутствием строки аргументов
  • Проверено, если какой-либо из файловых дескрипторов в библиотеках GNAT назван неправильно.
  • Перенаправил и stderr, и stdin на stdout, просто чтобы посмотреть, не сбрасывает ли GNAT их в неправильный FD.
  • Просмотрел досконально файл библиотеки System.OS_lib, и вроде бы нет причин.
  • Погуглил, но собственная страница GNAT на сайте GCC очень плохо документирована.

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

ОБНОВЛЕНИЕ: я попытался запустить его с абсолютным путем, как в /usr/bin, так и в /bin, и это не сработало. Интересно, что операционная система возвращает код результата 1, но я не знаю, что это значит. Быстрый поиск показывает, что это «все общие ошибки», а другой сайт предполагает, что это «неправильные функции».


person Bronze    schedule 19.09.2015    source источник


Ответы (2)


Мне пришлось немного подправить пример RosettaCode, чтобы запустить /bin/ls в Debian Linux, но он работает, как и ожидалось...

with Ada.Text_IO;     use Ada.Text_IO;
with Gnat.OS_Lib;   use Gnat.OS_Lib;

procedure Execute_Synchronously is
   Result    : Integer;
   Arguments : Argument_List :=
                 (  1=> new String'("-al")
                 );
begin
   Spawn
   (  Program_Name           => "/bin/ls",
      Args                   => Arguments,
      Output_File_Descriptor => Standout,
      Return_Code            => Result
   );
   for Index in Arguments'Range loop
      Free (Arguments (Index)); 
   end loop;
end Execute_Synchronously;

Изменения :

  1. мой Gnat (FSF Gnat 4.92 от Debian Jessie) предупредил о System.OS_Lib, рекомендуя вместо этого Gnat.OS_Lib. (Что просто переименовывает System.OS_Lib... почему???
    Комментарии System.OS_Lib:

-- Примечание: этот пакет находится в системной иерархии, поэтому его можно напрямую
-- использовать в других предопределенных пакетах. Доступ пользователя к этому пакету осуществляется через
-- переименование этого пакета в GNAT.OS_Lib (файл g-os_lib.ads).

  1. Имя программы, включая путь.
  2. Аргументы. В первый раз, когда я запустил его, он отобразил детали самого «ls», потому что ему было присвоено собственное имя в качестве первого аргумента, поэтому я удалил его, чтобы вместо этого увидеть текущий каталог.

Примечания :

  1. наилучшая информация о доступных подпрограммах и их аргументах обычно содержится в самих спецификациях пакетов в папке «adainclude»: это /usr/lib/gcc/x86_64-linux-gnu/4.9/adainclude в моей установке Debian, locate system.ads найдется в вашей. Конкретные файлы: s-os_lib.ads для System.OS_Lib, который экспортирует Spawn и Standout, и a-textio.ads для Ada.Text_IO.
  2. Standout не является предпочтительным способом доступа к стандартному выводу: это дескриптор файла (целое число), предпочтительным способом будет функция Standard_Output из Ada.Text_IO, которая возвращает файл. Однако, похоже, не существует перегрузки для Spawn, которая принимает файл (и я бы не ожидал его в этой низкоуровневой библиотеке), поэтому здесь используется файловый дескриптор более низкого уровня.
person user_1818839    schedule 19.09.2015

При отсутствии оболочки вам нужно будет выполнить поиск PATH самостоятельно или указать полный путь к нужному исполняемому файлу:

Spawn (
   Program_Name => "/bin/ls",
   …
);

Я попытался запустить его с абсолютным путем… ни /usr/bin, ни /bin не работают.

Используйте which, чтобы определить полный путь к исполняемому файлу:

$ which ls
/bin/ls
person trashgod    schedule 19.09.2015
comment
На самом деле подумав о добавлении переменной PATH, я чувствую себя глупо из-за того, что не пробовал этого. Я попробую это в ближайшее время - person Bronze; 19.09.2015
comment
@Bronze: вы можете использовать Getenv для допроса унаследованного PATH. - person trashgod; 19.09.2015