Эта структура содержит объединение (union), и первое поле структуры является
тегом, идентифицирующим содержимое этого объединения. В настоящий момент определено только одно поле объединения (структура d_desc, описывающая дескриптор), и тег (d_attributes) должен иметь значение DOOR_DESCRIPTOR.
Пример
Изменим наш пример с сервером файлов таким образом, чтобы сервер открывал файл, передавал дескриптор клиенту, а клиент копировал содержимое файла в стандартный поток вывода. На рис. 15.4 приведена схема приложения. В листинге 15.15 приведен текст программы клиента.
Листинг 15.15. Клиент для сервера, передающего дескриптор
9-15 Имя файла, связанного с дверью, принимается в качестве аргумента командной строки. Имя файла, который должен быть открыт и выведен, считывается из стандартного потока ввода, а завершающий символ перевода строки удаляется.
Подготовка аргументов и указателя на буфер возврата
16-22 Подготавливается структура door_arg_t. К размеру имени файла мы добавляем единицу, чтобы сервер мог дополнить его завершающим нулем.
Вызов процедуры сервера и проверка результатов
23-31 Мы вызываем процедуру сервера и проверяем результат. Должен возвращаться только один дескриптор и никаких данных. Вскоре мы увидим, что сервер возвращает данные (сообщение об ошибке) только в том случае, если он не может открыть файл. В этом случае функция err_quit выводит сообщение об ошибке.
Считывание дескриптора и копирование файла
32-34 Дескриптор извлекается из структуры door_desc_t, и файл копируется в стандартный поток вывода.
В листинге 15.16 приведен текст процедуры сервера. Функция main по сравнению с листингом 15.3 не изменилась.
Листинг 15.16. Процедура сервера, открывающая файл и возвращающая клиенту дескриптор
9-14 Мы завершаем полное имя файла клиента нулем и делаем попытку открыть этот файл вызовом open. Если возникает ошибка, сообщение о ней возвращается клиенту.
Успешное открытие файла
15-20 Если файл был успешно открыт, клиенту возвращается только его дескриптор.
Запустим сервер и укажем ему имя двери /tmp/fd1, а затем запустим клиент:
solaris % clientfd1 /tmp/fd1
/etc/shadow
/etc/shadow: can't open. Permission denied
solaris % clientfd1 /tmp/fd1
/no/such/file
/no/such/file: can't open. No such file or directory